package com.day1_栈和队列;

import java.util.Deque;
import java.util.LinkedList;

/**
 * 题目:剑指 Offer 30. 包含 min 函数的栈
 * 题目内容：定义栈的数据结构，请在该类型中实现一个能够得到栈的最小元素的 min 函数在该栈中，调用 min、push 及 pop 的时间复杂度都是 O(1)。
 * 示例:
 * MinStack minStack = new MinStack();
 * minStack.push(-2);
 * minStack.push(0);
 * minStack.push(-3);
 * minStack.min();   --> 返回 -3.
 * minStack.pop();
 * minStack.top();      --> 返回 0.
 * minStack.min();   --> 返回 -2.
 *
 * 思路：
 * 因为要求min函数时间复杂度为O(1),所以需要利用辅助栈，与元素栈同步插入和删除，用于存储与每个元素对于的最小值
 * 1.当向元素栈中插入数据时，同时比较辅助栈栈顶元素和新插入的数据的大小，将最小值插入到辅助栈中，辅助栈顶一直放最小值
 * 2.当删除一个元素时，则同时删除元素栈和辅助栈的栈顶元素
 * 时长：1h30m
 * 日期：20220815
 */
class MinStack {

    /** initialize your data structure here. */
    //java中已经放弃了Stack的使用，实现栈时最好用LinkedList,实现队列时最好用ArrayDeque
    Deque<Integer> xStack;//元素栈
    Deque<Integer> minStack;//辅助栈
    public MinStack() {
        xStack=new LinkedList<Integer>();
        minStack=new LinkedList<Integer>();
        minStack.push(Integer.MAX_VALUE);//push放法是在头部添加元素，即在栈顶插入
    }
    /*
     1.当向元素栈中插入数据时，同时比较辅助栈栈顶元素和新插入的数据的大小，将最小值插入到辅助栈中
      */
    public void push(int x) {
        xStack.push(x);
        minStack.push(Math.min(x,minStack.peek()));//peek()方法时返回头部元素，即栈顶元素
    }

    public void pop() {
        xStack.pop();
        minStack.pop();
    }

    public int top() {
        return xStack.peek();
    }

    public int min() {
        return minStack.peek();
    }
}

public class 剑指Offer30_包含min函数的栈 {
    public static void main(String[] args) {
        MinStack minStack=new MinStack();
        minStack.push(-2);
        minStack.push(0);
        minStack.push(-3);
        System.out.println(minStack.min());
        minStack.pop();
        System.out.println(minStack.top());
        System.out.println(minStack.min());
    }


}
